package com.hkyp.ss.course.provider.impl;

import com.hkyp.ss.course.apis.CourseCommentService;
import com.hkyp.ss.course.apis.dto.common.PageReq;
import com.hkyp.ss.course.apis.dto.common.PageResp;
import com.hkyp.ss.course.apis.dto.request.CourseCommentDTO;
import com.hkyp.ss.course.apis.dto.request.UpdateCourseCommentDTO;
import com.hkyp.ss.course.apis.dto.response.CourCommVO;
import com.hkyp.ss.course.apis.dto.response.SimpleCourCommVO;
import com.hkyp.ss.course.apis.dto.response.UserHPCourCommVO;
import com.hkyp.ss.course.apis.enumu.CourseStatusEnum;
import com.hkyp.ss.course.apis.enumu.YesNoEnum;
import com.hkyp.ss.course.apis.exception.ServiceException;
import com.hkyp.ss.course.apis.exception.UnacceptableException;
import com.hkyp.ss.course.apis.utils.BeanMapper;
import com.hkyp.ss.course.apis.utils.MyReflectionUtil;
import com.hkyp.ss.course.provider.model.Course;
import com.hkyp.ss.course.provider.model.CourseComment;
import com.hkyp.ss.course.provider.model.User;
import com.hkyp.ss.course.provider.model.mediate.CourCommVoter;
import com.hkyp.ss.course.provider.repository.CourCommRepository;
import com.hkyp.ss.course.provider.repository.CourseRepository;
import com.hkyp.ss.course.provider.repository.UserRepository;
import com.hkyp.ss.course.provider.repository.mediate.CourCommVoterRepository;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service(version = "1.0")
@Transactional(rollbackFor = Exception.class)
public class CourseCommentServiceImpl implements CourseCommentService {

    @Autowired
    CourseRepository courseRepository;

    @Autowired
    CourCommRepository courCommRepository;

    @Autowired
    UserRepository userRepository;

    @Autowired
    CourCommVoterRepository courCommVoterRepository;


    public void saveCourseComment(List courses){

        System.out.println(courCommRepository.saveAll(courses));


    }


    @Override
    @Transactional(readOnly = true)
    public PageResp<UserHPCourCommVO> selectCourseCommentByUserId(PageReq pageReq, Long userId,Long watcherUserId) {

        CourseComment courseComment = new CourseComment();
        courseComment = MyReflectionUtil.byField(courseComment);

        courseComment.setUserId(userId);
        courseComment.setStatus(0);
        courseComment.setDeleted(0);
        Example<CourseComment> courseCommentExample = Example.of(courseComment);
        Page<CourseComment> pageResp = courCommRepository.findAll(courseCommentExample,pageReq.toPageable());
        List<CourseComment> courseComments = pageResp.getContent();
        List<UserHPCourCommVO> userHPCourCommVOS = BeanMapper.mapList(courseComments, UserHPCourCommVO.class);

        //用户对此课评的投票字段赋值:  赞 中立 反对
        Set<Long> pageCcIds = courseComments.stream().map(CourseComment::getId).collect(Collectors.toSet());
        List<CourCommVoter> courCommVoters = courCommVoterRepository.findAllByCcIdInAndUserIdEquals(pageCcIds, watcherUserId);
        if(!CollectionUtils.isEmpty(courCommVoters)){
            Map<Long, CourCommVoter> ccIdObjMap = courCommVoters.stream().collect(Collectors.toMap(CourCommVoter::getCcId, obj -> obj));
            userHPCourCommVOS.forEach(userHPCourCommVO -> {
                CourCommVoter courCommVoter = ccIdObjMap.get(userHPCourCommVO.getId());
                if(courCommVoter!=null){
                    userHPCourCommVO.setVoter(courCommVoter.getType());
                }
            });
        }

        return new PageResp<>(pageResp,userHPCourCommVOS);
    }

    @Override
    @Transactional(readOnly = true)
    public PageResp<SimpleCourCommVO> selectCourseCommentList(PageReq pageReq, Long courseId,Long userId) {

        CourseComment courseComment = new CourseComment();
        courseComment = MyReflectionUtil.byField(courseComment);

        courseComment.setCourseId(courseId);
        courseComment.setStatus(0);

        Example<CourseComment> courseCommentExample = Example.of(courseComment);

        Page<CourseComment> pageResp = courCommRepository.findAll(courseCommentExample,pageReq.toPageable());

        List<CourseComment> courseCommentList = pageResp.getContent();

        // 用set可以去除重复元素
        Set<Long> userIdsSet = courseCommentList
        .stream()
        .map(CourseComment::getUserId)
        .collect(Collectors.toSet());

        log.info("获得的用户id为："+userIdsSet);

        List<User> userList = userRepository.findAllById(userIdsSet);
        // 转map
        Map<Long,User> userMap = userList
                .stream()
                .collect(Collectors.toMap(User::getId,user -> user));

        Map<Long,CourCommVoter> courCommVoterMap = null;
       if(userId != null){
           // 课评id集合
           Set<Long> ccIdSet = courseCommentList
                   .stream()
                   .map(CourseComment::getId)
                   .collect(Collectors.toSet());
           List<CourCommVoter> courCommVoterList = courCommVoterRepository.findAllByCcIdInAndUserIdEquals(ccIdSet, userId);
           log.info("用户在当前页面的投票数据："+courCommVoterList);
           // 转map
           if(!CollectionUtils.isEmpty(courCommVoterList)){
               courCommVoterMap = courCommVoterList
                       .stream()
                       .collect(Collectors.toMap(CourCommVoter::getCcId,voter -> voter));
           }
       }

        List<SimpleCourCommVO> simpleCourCommVOList = new ArrayList<>();
        Map<Long,CourCommVoter> courCommVoterMapLambda = courCommVoterMap;
        courseCommentList.forEach(courComm -> {

            SimpleCourCommVO simpleCourCommVO = BeanMapper.map(courComm, SimpleCourCommVO.class);
            simpleCourCommVO.setIssueTime(courComm.getCreateAt()); // 发布时间
            User user = userMap.get(courComm.getUserId());
            simpleCourCommVO.setAvatar(user.getAvatar());
            simpleCourCommVO.setFansNum(user.getFansNum());
            simpleCourCommVO.setNickName(user.getNickName());
            simpleCourCommVO.setUserId(user.getId());

            if(!CollectionUtils.isEmpty(courCommVoterMapLambda)){
                CourCommVoter courCommVoter = courCommVoterMapLambda.get(courComm.getId());
                if(courCommVoter == null){
                    log.info("【空指针预警】courseId: {},ccid: {},userId: {}, 查出的CourCommVoter为空",courseId,courComm.getId(),userId);
                    simpleCourCommVO.setVoter(0);
                }else {
                    simpleCourCommVO.setVoter(courCommVoter.getType());
                }
            }

            simpleCourCommVOList.add(simpleCourCommVO);
        });


        return new PageResp<>(pageResp, simpleCourCommVOList);
    }

    @Override
    @Transactional(readOnly = true)
    public CourCommVO selectCourseComment(Long ccId) {

        CourseComment courseComment = courCommRepository.findById(ccId).orElse(null);
        if(courseComment == null){
            return null;
        }
        return BeanMapper.map(courseComment,CourCommVO.class);
    }

    @Override
    public void addCourseComment(CourseCommentDTO courseCommentDTO) {
        Integer ccScore = courseCommentDTO.getScore();
        if(ccScore == null){
            throw new UnacceptableException("请填写评分");
        }
        Course course =  courseRepository.findById(courseCommentDTO.getCourseId())
                .orElseThrow( () -> new ServiceException("没有找到您输入的课程id所对应的课程"));
        List<CourseComment> courseCommentList = courCommRepository.findByCourseIdAndUserIdAndDeletedAndStatus(courseCommentDTO.getCourseId(), courseCommentDTO.getUserId(), YesNoEnum.NO.getCode(), CourseStatusEnum.NORMAL.getCourseStatus());
        if(!CollectionUtils.isEmpty(courseCommentList)){
            throw new UnacceptableException("您已经为此课程添加过课评");
        }

        CourseComment courseComment = BeanMapper.map(courseCommentDTO,CourseComment.class);

        courseComment.setUserId(courseCommentDTO.getUserId());
        courseComment.setTitle(course.getTitle());
        courseComment.setCreateAt(System.currentTimeMillis());
        courCommRepository.save(courseComment);

        //课程评分计算
        Integer comScore = course.getComScore();
        Integer commentNum = course.getCommentNum();
        if(comScore == null){
            comScore = 0;
        }
        if(commentNum == null){
            commentNum = 0;
        }
        int result = ((commentNum*comScore)+ccScore)/(commentNum+1);
        course.setComScore(result);
        //对课程的课评数属性加一
        course.setCommentNum(course.getCommentNum()+1);
        courseRepository.save(course);

    }

    public void updateCourseComment(UpdateCourseCommentDTO courseCommentDTO) throws UnacceptableException{
        Integer newScore = courseCommentDTO.getScore();
        if(newScore == null){
            throw new UnacceptableException("请输入评分！");
        }

        CourseComment courseComment = courCommRepository.findById(courseCommentDTO.getCcid())
                                                        .orElseThrow(() -> new UnacceptableException("修改的课评不存在"));
        if(!Objects.equals(courseComment.getUserId(),courseCommentDTO.getUserId())){
            log.error("该用户尝试修改别人的课评,登录者id:{}, 要修改的课评所有人id:{}",courseCommentDTO.getUserId(),courseComment.getUserId());
            throw new UnacceptableException("修改失败！");
        }

        // 穿插：课程相关更新
        Course course =  courseRepository.findById(courseComment.getCourseId())
                .orElseThrow( () -> new ServiceException("没有找到您输入的课程id所对应的课程"));

        //课程评分计算
        Integer comScore = course.getComScore();
        Integer commentNum = course.getCommentNum();
        Integer commentScore = courseComment.getScore();
        if(comScore == null){
            comScore = 0;
        }
        if(commentNum == null){
            commentNum = 0;
        }
        int result = ((commentNum*comScore)-commentScore+newScore)/commentNum;
        course.setComScore(result);
        courseRepository.save(course);

        // 继续课评更新
        courseComment.setContent(courseCommentDTO.getContent());
        courseComment.setLearnability(courseCommentDTO.getLearnability());
        courseComment.setPracticability(courseCommentDTO.getPracticability());
        courseComment.setLogicality(courseCommentDTO.getLogicality());
        courseComment.setScore(courseCommentDTO.getScore());
        courCommRepository.save(courseComment);

    }

    public void saveCourse(List courseComment){

        System.out.println(courCommRepository.saveAll(courseComment));


    }

}
